﻿using LightCAD.Three.OpenGL;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace LightCAD.Three
{
    public class Image : EventDispatcher, IImage
    {
        public string crossOrigin;
        public string src;
        public string uuid;
        public Array data;
        public Bitmap bmp;

        public bool complete;
        public bool flipped { get; private set; } = false;
        public int size
        {
            get { return 0; }
        }
        public int width { get; set; }
        public int height { get; set; }
        public int depth { get; set; }
        private int alpha = -1;
        public bool detectAlpha()
        {
            if (alpha >= 0)
            {
                return alpha == 1;
            }
            for (int y = 0; y < bmp.Height; ++y)
            {
                for (int x = 0; x < bmp.Width; ++x)
                {
                    if (bmp.GetPixel(x, y).A != 255)
                    {
                        alpha = 1;
                        return true;
                    }
                }
            }
            alpha = 0;
            return false;
        }
        public void flipY()
        {
            bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
            flipped = !flipped;
        }

        private System.Drawing.Imaging.BitmapData readData;
        private GCHandle? dataGCHandle;
        internal IntPtr startRead(int type  = gl.UNSIGNED_BYTE)
        {
            if (this.bmp != null)
            {
                //var hasAlpha = detectAlpha();
                this.readData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                                      System.Drawing.Imaging.ImageLockMode.ReadOnly,
                                      System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                return this.readData.Scan0;
            }
            else
            {
                Array data = null;
                if (type == gl.FLOAT)
                {
                    if (this.data is float[])
                        data = this.data;
                    else if (this.data is double[])
                    {
                        data = new float[this.data.Length];
                        for (int i = 0; i < this.data.Length; i++)
                        {
                            data.SetValue(Convert.ToSingle(this.data.GetValue(i)), i);
                        }
                    }
                }
                else if (type ==  gl.HALF_FLOAT)
                {
                    if (this.data is ushort[])
                        data = this.data;
                    else
                    {
                        console.error("无效的类型转换: GL.HALF_FLOAT 不支持其他类型的数组");
                        //data = new ushort[this.data.Length];
                        //for (int i = 0; i < this.data.Length; i++)
                        //{
                        //    data.SetValue(Convert.ToUInt16(this.data.GetValue(i)), i);
                        //}
                    }
                }
                else data = this.data;
                //else if(format==GL.INT)其他格式用到再加
                dataGCHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
                if (dataGCHandle.Value.IsAllocated)
                    return dataGCHandle.Value.AddrOfPinnedObject();
                else return IntPtr.Zero;
                //return IntPtr.Zero;
            }
        }
        public void endRead()
        {
            if (this.readData != null)
            {
                this.bmp.UnlockBits(this.readData);
                this.readData = null;
            }
            else
            {
                var handle = dataGCHandle.Value;
                dataGCHandle = null;
                handle.Free();
            }
        }
        public Image clone()
        {
            return new Image
            {
                crossOrigin = this.crossOrigin,
                src = this.src,
                uuid = this.uuid,
                data = this.data,
                //bmp = this.bmp,
                width = this.width,
                height = this.height,
                depth = this.depth,
                complete = this.complete,
                flipped = this.flipped,
                alpha = this.alpha
            };
        }
        public IImage cloneImage() => clone();
        public void loadLocal(string src)
        {
            this.bmp = (Bitmap)Bitmap.FromFile(src);
            this.loadBitMap(bmp, src);
        }
        private Image loadBitMap(Bitmap bitmap, string src = null)
        {
            this.src = src;
            this.bmp = bitmap;
            this.width = this.bmp.Width;
            this.height = this.bmp.Height;
            //不用异步
            this.dispatchEvent(new EventArgs(this, "load"));
            this.complete = true;
            return this;
        }
    }
}
